/*
 * @Author       : Wang.XuanXuan xuanxuan.wang@wbstar.com
 * @Date         : 2024-05-20 22:11:04
 * @LastEditors  : Wang.XuanXuan xuanxuan.wang@wbstar.com
 * @LastEditTime : 2025-03-15 13:09:53
 * @FilePath     : \openchaoji-corelib\evcc\utility\OpenChaoJi_evcc_utility_linkage.c
 * @Description  : 本文件定义EVCC Utility层 linkage 链路层协商和链路检测 模块
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "OpenChaoJi_evcc.h"

#include "string.h"

/**
 * @brief 本模块的上下文数据结构
 */
struct OpenChaoJi_evcc_context_utility_linkage
{
	/**
	 * 本EVCC使用的系统类型, 目前仅支持B类, A类不需要链路检测
	*/
	enum OpenChaoJi_evcc_gbt27930_type evcc_gbt27930_type;

	// 创建时候的传进来的参数
	struct OpenChaoJi_evcc_create_info_utility_linkage evcc_create_info;

	// 链路检测开始标识
	enum OpenChaoJi_evcc_utility_linkage_link_check_flag evcc_linkage_flag;

	// 版本协商子步骤
	enum OpenChaoJi_evcc_utility_linkage_version_confirm_step evcc_linkage_version_step;

	// 链路检测子步骤
	enum OpenChaoJi_evcc_utility_linkage_link_check_step evcc_linkage_check_step;

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)

	// EVCC版本协商超时定时器 Tv
	struct OpenChaoJi_os_soft_timer version_confer_Tv;

	// 上层发送数据帧定时器T1(超时1000ms)
	struct OpenChaoJi_os_soft_timer linkage_T1;

	// 接收车辆数据帧定时器T2(超时3000ms)
	struct OpenChaoJi_os_soft_timer linkage_T2;

	// 接收到的id
	uint32_t revc_msg_id;

	// 接收到的长度
	uint16_t revc_msg_len;

	// 收到数据的buff, 这里特指"版本协商报文"
	uint8_t ver_consult_buff[LINKAGE_SEND_MSG_MAX_LEN];

	// 收到数据"版本协商"的标识
	uint8_t revc_ver_consult_flag;

	// 收到数据其他报文的标识
	uint8_t revc_flag;

	// 上层有数据发送
	uint8_t send_flag;


	// 数据发送的buff
	uint8_t send_msg_buff[LINKAGE_SEND_MSG_MAX_LEN];

	// 发送函数的参数
	void *write_func_param;
	// 发送函数
	int (*write_func)(void *param, struct OpenChaoJi_utility_data_buff_send_data * send_data);


	// 下列是为了log新增的变量
	// 链路检测开始标识
	enum OpenChaoJi_evcc_utility_linkage_link_check_flag evcc_linkage_flag_log;
	// 版本协商子步骤
	enum OpenChaoJi_evcc_utility_linkage_version_confirm_step evcc_linkage_version_step_log;
	// 链路检测子步骤
	enum OpenChaoJi_evcc_utility_linkage_link_check_step evcc_linkage_check_step_log;
	// 最后一次打印log时间
	uint32_t last_time_printf_log_systick;
#endif
};

/**
 * @brief 获取linux系统的上电到现在的运行时长(ms)
 *
 * @param info
 * @return 返回linux系统的运行时长
 */
unsigned int OpenChaoJi_evcc_utility_linkage_get_systick(void)
{
	return  OpenChaoJi_os_get_ticks();
}


/**
 * @brief 初始化数据, 在创建&复位的时候调用
 *
 * @param info 初始化信息
 * @return 成功返回创建的上下文指针，失败返回NULL。
 */

static void OpenChaoJi_evcc_utility_linkage_init_type(struct OpenChaoJi_evcc_context_utility_linkage * context, enum OpenChaoJi_evcc_gbt27930_type evcc_gbt27930_type)
{
	context->evcc_gbt27930_type = evcc_gbt27930_type;
	context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT;
	context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;
	context->evcc_linkage_flag = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_STOP;

	return;
}

/**
 * @brief 初始化
 *
 * @param info 初始化信息
 * @return 成功返回创建的上下文指针，失败返回NULL。
 */
struct OpenChaoJi_evcc_context_utility_linkage * OpenChaoJi_evcc_utility_linkage_init(const struct OpenChaoJi_evcc_create_info_utility_linkage * info)
{
	if (NULL == info)
	{
		LOG_CRIT("Invalid Info");
		return NULL;
	}

	// 申请资源
	struct OpenChaoJi_evcc_context_utility_linkage * context = (struct OpenChaoJi_evcc_context_utility_linkage *)OpenChaoJi_os_malloc(sizeof(struct OpenChaoJi_evcc_context_utility_linkage));
    if (context == NULL)
    {
    	LOG_CRIT("Mallco context failed");
        return NULL;
    }
	else
	{
		// 清除数据
		memset(context, 0, sizeof(struct OpenChaoJi_evcc_context_utility_linkage));

		// 数据初始化
		OpenChaoJi_evcc_utility_linkage_init_type(context, info->evcc_gbt27930_type);

		// 复制创建参数
		context->evcc_create_info = *info;

		return context;
	}
}

/**
 * @brief 销毁
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_evcc_utility_linkage_term(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");

		return -1;
	}

	// 释放资源
	OpenChaoJi_os_free(context);
	return 0;
}

/**
 * @brief 复位
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_evcc_utility_linkage_reset(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

	// 数据初始化
	OpenChaoJi_evcc_utility_linkage_init_type(context, context->evcc_gbt27930_type);

	return 0;
}

/**
 * @brief 启动链路版本协商和链路检测
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param write_func 发送数据的方法, 用于发送版本协商和链路检测数据包
 * @param param write_func方法所需要的私有参数, 一般是传输层句柄
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_evcc_utility_linkage_start(struct OpenChaoJi_evcc_context_utility_linkage * context
		, int (*write_func)(void *param, struct OpenChaoJi_utility_data_buff_send_data * send_data), void * param)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	context->write_func = write_func;

	context->write_func_param = param;

	// 链路检测开始标识改为START
	context->evcc_linkage_flag = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_START;

	// 初始化
	context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT;

	// 链路检测初始化
	context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;

	return 0;
#endif

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_A == CONFIG_YES)
	// A类系统默认链路一直正常(不需要协商和检测)
	context->evcc_linkage_flag = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_START;
	context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_SUCCEED;
	context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_NORMAL;

	return 0;
#endif
}

/**
 * @brief 停止链路检测和版本协商(如存在)
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_evcc_utility_linkage_stop(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

    LOG_ALERT("[%d]Linkage Stop", context->evcc_create_info.tag);

	OpenChaoJi_evcc_utility_linkage_init_type(context, context->evcc_gbt27930_type);

	return 0;
}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)

/**
 * @brief 发送EVCC版本协议报文
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param interval_ms 发送的周期(ms)
 * @param cnt 发送的次数, -1为一直发送
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_evcc_utility_linkage_send_consult_msg(struct OpenChaoJi_evcc_context_utility_linkage * context, enum OpenChaoJi_evcc_utility_linkage_version_res_type version_res, int tag, int interval_ms, int cnt)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

	struct OpenChaoJi_utility_data_buff_send_data send_data;

	// 1. 消息的id
	send_data.tag.gbt.sa = OPENCHAOJI_GBT27930_B_CAN_ADDR_EVCC;
	send_data.tag.gbt.ps = OPENCHAOJI_GBT27930_B_CAN_ADDR_SECC;
	send_data.tag.gbt.pf = LINKAGE_CONSULT_MSG_ID_PF;
	send_data.tag.gbt.p = LINKAGE_CONSULT_MSG_ID_P;
	send_data.tag.gbt.ack = LINKAGE_CONSULT_MSG_ID_DP;
	send_data.tag.gbt.data_type = OPENCHAOJI_GBT27930_SYSTEM_B_LINKAGE_DATA;

	// 2. 消息的长度
	send_data.send_data.len = LINKAGE_EVCC_CONSULT_MSG_LEN;

	// 数据域初始化
	memset(context->send_msg_buff, LINKAGE_RESERVED_TYPE, LINKAGE_EVCC_CONSULT_MSG_LEN);

	// 3.1 数据域第1字节, CAN类型
	context->send_msg_buff[0] = context->evcc_create_info.gbt27930_info.gbt27930_b.can_type;

	// 3.2 协商结果
	context->send_msg_buff[1] = version_res;

	// 3.3 版本号
	context->send_msg_buff[2] = OPENCHAOJI_GBT27930_B_PROTOCOL_VERSION_TYPE_MAJOR(context->evcc_create_info.gbt27930_info.gbt27930_b.evcc_version);
	context->send_msg_buff[3] = OPENCHAOJI_GBT27930_B_PROTOCOL_VERSION_TYPE_MINOR(context->evcc_create_info.gbt27930_info.gbt27930_b.evcc_version);
	context->send_msg_buff[4] = OPENCHAOJI_GBT27930_B_PROTOCOL_VERSION_TYPE_TMP(context->evcc_create_info.gbt27930_info.gbt27930_b.evcc_version);

	// 填入buff
	send_data.send_data.data = context->send_msg_buff;

	// 4.1 tag
	//send_data.tag = tag;

	// 4.2 发送周期
	send_data.interval_ms = interval_ms;

	// 4.3 发送次数
	send_data.cnt = cnt;

	// 发送函数和句柄均有的情况下, 执行发送指令
	if( (NULL != context->write_func)
		&& (NULL != context->write_func_param) )
	{
		context->write_func(context->write_func_param, &send_data);
	}

	LOG_DATA_LINKAGE("[%d]VerNego->[%s][%s][%d.%d.%d]", context->evcc_create_info.tag
		, enum_names_OpenChaoJi_gbt27930_b_CANType(context->send_msg_buff[0])
		, enum_names_OpenChaoJi_gbt27930_b_VersionResultType(context->send_msg_buff[1])
		, context->send_msg_buff[2], context->send_msg_buff[3], context->send_msg_buff[4]);

	LOG_DATA_BUFF_LINKAGE(context->send_msg_buff, LINKAGE_SECC_CONSULT_MSG_LEN);

	return 0;
}
#endif

/**
 * @brief 服务, 链路版本协商和链路检测存在异步处理, 所以每次service触发内部处理
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
void OpenChaoJi_evcc_utility_linkage_service(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return ;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	LOG_DEBUG("[%d]evcc_utility_linkage_service", context->evcc_create_info.tag);

	// 查看有没有启动检测
	if(OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_STOP == context->evcc_linkage_flag)
	{
		// 直接就是S1
		context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT;

		// 链路检测初始化
		context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;

		// 收到数据的标识
		context->revc_flag = 0;

		// 收到数据"版本协商"的标识
		context->revc_ver_consult_flag = 0;
	}
	else if(OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_START == context->evcc_linkage_flag)
	{
		// 版本协商步骤
		switch(context->evcc_linkage_version_step)
		{
		case OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT:
			LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT", context->evcc_create_info.tag);
			// 开启Tv
			OpenChaoJi_os_soft_timer_start(&context->version_confer_Tv, LINKAGE_CONSULT_MSG_TC_PERIOD);

			// 进入S1
			context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_ING;
			break;

		case OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_ING:

			// 收到"充电机协议版本帧"
			if(1 == context->revc_ver_consult_flag)
			{
				context->revc_ver_consult_flag = 0;

				// 充电机CAN类型不等于CAN2.0
				if (OPENCHAOJI_GBT27930_B_CAN_TYPE_20 != context->ver_consult_buff[0])
				{
					// 发送"协商失败"信息
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_FAILED, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);

					// 进入S3, 协商失败
					context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_FAILED;
					LOG_STATUS_CHANGE("[%d]VersionNegoFailed:NotCAN2.0", context->evcc_create_info.tag);
				}
				// 支持"充电机协商的版本号"
				else if( OPENCHAOJI_GBT27930_B_PROTOCOL_VERSION_TYPE_MAKE(context->ver_consult_buff[1],context->ver_consult_buff[2], context->ver_consult_buff[3])
					 == (context->evcc_create_info.gbt27930_info.gbt27930_b.evcc_version) )
				{
					// 发送"协商成功"信息
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_SUCCEED, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);

					// 进入S2, 协商成功
					context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_SUCCEED;
					LOG_STATUS_CHANGE("[%d]VersionNegoSucceed", context->evcc_create_info.tag);
				}
				// 不支持"充电机协商的版本号"及更低的版本号
				else if( OPENCHAOJI_GBT27930_B_PROTOCOL_VERSION_TYPE_MAKE(context->ver_consult_buff[1],context->ver_consult_buff[2], context->ver_consult_buff[3])
					 != (context->evcc_create_info.gbt27930_info.gbt27930_b.evcc_version) )
				{
					// 发送"协商失败"信息
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_FAILED, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);

					// 进入S3, 协商失败
					context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_FAILED;
					LOG_STATUS_CHANGE("[%d]VersionNegoFailed:InvalidVersion", context->evcc_create_info.tag);
				}
				// 不支持"充电机协商的版本号", 但支持比"充电机协商的版本号"更低的版本号
				else
				{
					// 发送"继续协商"
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_CONTINUE, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);
				}
			}

			// Tv定时器时间到
			if(OpenChaoJi_os_soft_timer_is_timeout(&context->version_confer_Tv))
			{
				// 进入S3, 协商失败
				context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_FAILED;
				LOG_STATUS_CHANGE("[%d]VersionNegoFailed:Timeout", context->evcc_create_info.tag);
			}
			break;

		case OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_SUCCEED:
			LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_SUCCEED", context->evcc_create_info.tag);
			// 关闭Tv定时器
			OpenChaoJi_os_soft_timer_stop(&context->version_confer_Tv);
			break;

		case OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_FAILED:
			LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_FAILED", context->evcc_create_info.tag);
			// 关闭Tv定时器
			OpenChaoJi_os_soft_timer_stop(&context->version_confer_Tv);
			break;

		default:
			context->evcc_linkage_version_step = OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_ING;
			break;
		}


		// 链路检测步骤
		if(OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_SUCCEED == context->evcc_linkage_version_step)
		{
			switch(context->evcc_linkage_check_step)
			{
			case OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT:
				LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT", context->evcc_create_info.tag);

				// 清除接收到数据标识
				context->revc_flag = 0;
				context->revc_ver_consult_flag = 0;

				// 数据发送清0
				context->send_flag = 0;

				// 打开T1
				OpenChaoJi_os_soft_timer_start(&context->linkage_T1, LINKAGE_WITNOUT_OTHER_MSG_T1_TIME);

				// 打开T2
				OpenChaoJi_os_soft_timer_start(&context->linkage_T2, LINKAGE_WITNOUT_OTHER_MSG_T2_TIME);

				// 进入S1: 不可信
				context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_UNTRUSTABLE;
				break;

			case OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_UNTRUSTABLE:
			case OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_NORMAL:
				LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_UNTRUSTABLE/NORMAL", context->evcc_create_info.tag);

				// 上层有数据帧发送
				if(context->send_flag)
				{
					context->send_flag = 0;

					// 重置T1
					OpenChaoJi_os_soft_timer_start(&context->linkage_T1, LINKAGE_WITNOUT_OTHER_MSG_T1_TIME);
				}

				// T1定时器到
				if(OpenChaoJi_os_soft_timer_is_timeout(&context->linkage_T1))
				{
					// 重置T1
					OpenChaoJi_os_soft_timer_start(&context->linkage_T1, LINKAGE_WITNOUT_OTHER_MSG_T1_TIME);

					// 发送一次"版本协商"
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_SUCCEED, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);
				}

				// 接收"充电机数据帧"
				if( (1 == context->revc_flag)
					|| (1 == context->revc_ver_consult_flag) )
				{
					//清除接收到数据标识
					context->revc_flag = 0;
					context->revc_ver_consult_flag = 0;

					// 进入S2, 通信链路状态正常
					context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_NORMAL;

					// 重置T2
					OpenChaoJi_os_soft_timer_start(&context->linkage_T2, LINKAGE_WITNOUT_OTHER_MSG_T2_TIME);
				}

				// T2定时器到
				if(OpenChaoJi_os_soft_timer_is_timeout(&context->linkage_T2))
				{
					// 进入S3, 通信链路状态不正常
					context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_ABNORMAL;

					// 关闭T2
					OpenChaoJi_os_soft_timer_stop(&context->linkage_T2);
				}
				break;


			case OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_ABNORMAL:
				LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_ABNORMAL", context->evcc_create_info.tag);
				// 上层有数据帧发送
				if(context->send_flag)
				{
					context->send_flag = 0;

					// 重置T1
					OpenChaoJi_os_soft_timer_start(&context->linkage_T1, LINKAGE_WITNOUT_OTHER_MSG_T1_TIME);
				}

				// T1定时器到
				if(OpenChaoJi_os_soft_timer_is_timeout(&context->linkage_T1))
				{
					// 重置T1
					OpenChaoJi_os_soft_timer_start(&context->linkage_T1, LINKAGE_WITNOUT_OTHER_MSG_T1_TIME);

					// 发送一次"版本协商"
					OpenChaoJi_evcc_utility_linkage_send_consult_msg(context, OPENCHAOJI_EVCC_LINKAGE_VER_RES_SUCCEED, LINKAGE_EVCC_CONSULT_MSG_TAG, LINKAGE_SECC_CONSULT_MSG_PERIOD, 1);
				}

				// 接收"充电机数据帧"
				if( (1 == context->revc_flag)
					|| (1 == context->revc_ver_consult_flag) )
				{
					//清除接收到数据标识
					context->revc_flag = 0;
					context->revc_ver_consult_flag = 0;

					// 进入S2, 通信链路状态正常
					context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_NORMAL;

					// 重置T2
					OpenChaoJi_os_soft_timer_start(&context->linkage_T2, LINKAGE_WITNOUT_OTHER_MSG_T2_TIME);
				}
				break;

			case OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_END:
				LOG_DEBUG("[%d]OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_END", context->evcc_create_info.tag);
				// 关闭T1
				OpenChaoJi_os_soft_timer_stop(&context->linkage_T1);

				// 关闭T2
				OpenChaoJi_os_soft_timer_stop(&context->linkage_T2);
				break;

			default:
				context->evcc_linkage_check_step = OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;
				break;
			}
		}
	}


	#ifdef LINKAGE_DEBUG
	if( (context->evcc_linkage_flag != context->evcc_linkage_flag_log)
		|| (context->evcc_linkage_version_step != context->evcc_linkage_version_step_log)
		|| (context->evcc_linkage_check_step != context->evcc_linkage_check_step_log)
		|| ( (OpenChaoJi_evcc_utility_linkage_get_systick() - context->last_time_printf_log_systick) > LINKAGE_DEBUG_PRINTF_LOG_PERIOD) )
	{
		context->evcc_linkage_flag_log = context->evcc_linkage_flag;
		context->evcc_linkage_version_step_log = context->evcc_linkage_version_step;
		context->evcc_linkage_check_step_log = context->evcc_linkage_check_step;

		// 更新时间
		context->last_time_printf_log_systick = OpenChaoJi_evcc_utility_linkage_get_systick();


		LOG_DEBUG("OpenChaoJi_evcc_utility_linkage_service evcc_linkage_flag=%d, evcc_linkage_version_step=%d, evcc_linkage_check_step=%d",
		context->evcc_linkage_flag,
		context->evcc_linkage_version_step,
		context->evcc_linkage_check_step);

		LOG_DEBUG("[%d]evcc_linkage_flag=%d, evcc_linkage_version_step=%d, evcc_linkage_check_step=%d"
		, context->evcc_create_info.tag
		, context->evcc_linkage_flag
		, context->evcc_linkage_version_step
		, context->evcc_linkage_check_step);
	}
	#endif
#endif
}


/**
 * @brief 上传发送数据调用该接口, 如果上次长时间没有发送数据, 链路检测则发送"版本协商"报文
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param last_ticks 最后一次发送数据的时间
 * @return 本模块已接收返回1，本模块未处理返回0。
 */
int OpenChaoJi_evcc_utility_linkage_send_data_ticks(struct OpenChaoJi_evcc_context_utility_linkage * context, uint32_t last_ticks)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	context->send_flag = 1;
#endif
	return 0;
}


/**
 * @brief 收到数据, 描述是否是链路检测模块所需要的数据
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 收到的链路层数据
 * @return 本模块已接收返回1, 本模块未处理返回0。
 */
int OpenChaoJi_evcc_utility_linkage_is_linkage_data(struct OpenChaoJi_evcc_context_utility_linkage * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data)
{
	if( (NULL == context)
		|| (NULL == recv_data) )
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	// 是EVCC的版本协商帧
	if ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_SECC == recv_data->tag.gbt.sa) &&
		(OPENCHAOJI_GBT27930_B_CAN_ADDR_EVCC == recv_data->tag.gbt.ps) &&
		(LINKAGE_CONSULT_MSG_ID_PF == recv_data->tag.gbt.pf) &&
		(LINKAGE_CONSULT_MSG_ID_P == recv_data->tag.gbt.p) )
	{
		LOG_DEBUG("recv version pack");
		return 1;
	}
#endif

	return 0;
}


/**
 * @brief 收到通信报文, 通知链路检测, 用于刷新检测通信链路断开的超时时间
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param last_ticks 最后一次收到通信报文的systick
 * @return 本模块无异常返回0, 有异常返回其他值。
 */

int OpenChaoJi_evcc_utility_linkage_revc_data_ticks(struct OpenChaoJi_evcc_context_utility_linkage * context, uint32_t last_ticks)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	context->revc_flag = 1;
#endif

	return 0;
}


/**
 * @brief 收到数据, 版本协商或者链路检测相关数据帧需要交给本模块处理. 如果不是链路层数据, 则只更新链路超时计时器
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 收到的链路层数据
 * @return 本模块已接收返回1，本模块未处理返回0。
 */
int OpenChaoJi_evcc_utility_linkage_got_data(struct OpenChaoJi_evcc_context_utility_linkage * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data)
{
	int res;
	if( (NULL == context)
		|| (NULL == recv_data) )
	{
		LOG_CRIT("Invalid Context");
		return -1;
	}
	res = 0;

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	// 是EVCC的版本协商帧
	if ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_SECC == recv_data->tag.gbt.sa) &&
		(OPENCHAOJI_GBT27930_B_CAN_ADDR_EVCC == recv_data->tag.gbt.ps) &&
		(LINKAGE_CONSULT_MSG_ID_PF == recv_data->tag.gbt.pf) &&
		(LINKAGE_CONSULT_MSG_ID_P == recv_data->tag.gbt.p) )
	{
		// 长度
		context->revc_msg_len = recv_data->recv_data.len;
		if(context->revc_msg_len > LINKAGE_SEND_MSG_MAX_LEN)
		{
			context->revc_msg_len = LINKAGE_SEND_MSG_MAX_LEN;
		}

		// 数据域
		if(NULL != recv_data->recv_data.data)
		{
			memcpy(context->ver_consult_buff, recv_data->recv_data.data, context->revc_msg_len);

			LOG_DATA_LINKAGE("[%d]VerNego<-[%s][%d.%d.%d]", context->evcc_create_info.tag
				, enum_names_OpenChaoJi_gbt27930_b_CANType(context->ver_consult_buff[0])
				, context->ver_consult_buff[1], context->ver_consult_buff[2], context->ver_consult_buff[3]);
			LOG_DATA_BUFF_LINKAGE(context->ver_consult_buff, context->revc_msg_len);

			context->revc_ver_consult_flag = 1;
		}
		res = 1;
	}


	#ifdef LINKAGE_DEBUG
	LOG_DEBUG("OpenChaoJi_evcc_utility_linkage_got_data recv_data: res=%d, msg_id=0x%X, revc_msg_len=%d, recv_tick=%d",
		res, recv_data->tag.all, recv_data->recv_data.len, recv_data->recv_tick);
	#endif
#endif

	return res;
}

/**
 * @brief B系统链路版本协商结果获取函数
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 返回版本协商状态
 */
enum OpenChaoJi_evcc_utility_linkage_version_confirm_step OpenChaoJi_evcc_utility_linkage_get_version_confer_state(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	if(OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_START == context->evcc_linkage_flag)
	{
		return context->evcc_linkage_version_step;
	}
#endif

	return OPENCHAOJI_EVCC_LINKAGE_VERSION_CONFER_STEP_INIT;
}

/**
 * @brief B系统链路检测结果获取函数
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 返回链路检测结果
 */
enum OpenChaoJi_evcc_utility_linkage_link_check_step OpenChaoJi_evcc_utility_linkage_get_link_check_state(struct OpenChaoJi_evcc_context_utility_linkage * context)
{
	if(NULL == context)
	{
		LOG_CRIT("Invalid Context");
		return OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;
	}

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
	// 开始检测后, 才有链路检测的结果
	if(OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_FLAG_START == context->evcc_linkage_flag)
	{
		return context->evcc_linkage_check_step;
	}
#endif
	return OPENCHAOJI_EVCC_LINKAGE_LINK_CHECK_STEP_INIT;
}


